package com.ying.tests.lambda;


import java.util.function.Function;

public class Test {

    /*public final int value = 4;
    public void doIt() {
        int value = 6;
        Runnable runnable = new Runnable() {
            public final int value = 5;
            public void run() {
                int value = 10;
                System.out.println(this.value);// 5
            }
        };
        runnable.run();
    }
    public static void main(String[] args) {
        Test test = new Test();
        test.doIt();
    }*/
//--------------------------------------------------------------------------------------------------
    /*@FunctionalInterface
    public interface BufferedReaderProcessor {
        String process(BufferedReader b) throws IOException;
    }
    public static String processFile(BufferedReaderProcessor p) throws IOException {
        BufferedReader br = new BufferedReader(new FileReader("data.txt"));
        return p.process(br);
    }*/
//--------------------------------------------------------------------------------------------------
    /*public static void main(String[] args) throws IOException {
        String result1 = processFile((BufferedReader br) -> br.readLine());
        String result2 = processFile((BufferedReader br) -> br.readLine() + br.readLine());

        Function<Integer, Integer> a = x -> x + 1;
        Function<Integer, Integer> b = x -> x * 2;

        Function<Integer, Integer> c = a.andThen(b);
        Integer result1 = c.apply(1);// result1 = 4
        System.out.println(result1);

        Function<Integer, Integer> d = a.compose(b);
        Integer result2 = d.apply(1);// result2 = 3
        System.out.println(result2);

        // 求1,2,3,4,5这个数组各个元素的平方
        List<Integer> list = Arrays.asList(1,2,3,4,5);
        List<Integer> collect = list
                .stream()
                .map(v -> v * v)
                .collect(Collectors.toList());
        System.out.println(collect);
        // 给定两个数字列表a=[1,2,3],b=[3,4]，求其笛卡尔积。
        // a x b = [(1,3)(1,4)(2,3)(2,4)(3,3)(3,4)]
        List<Integer> a = Arrays.asList(1,2,3);
        List<Integer> b = Arrays.asList(3,4);
        List<int[]> collect = a
                .stream()
                .flatMap(i -> b.stream().map(j -> new int[]{i, j}))
                .collect(Collectors.toList());
        collect.stream().forEach(result -> {
            System.out.println(Arrays.toString(result));
        });
        // 扩展上面的结果，只返回总和能被3整除的数对，例如(2,4)(3,3)
        List<Integer> a = Arrays.asList(1,2,3);
        List<Integer> b = Arrays.asList(3,4);
        List<int[]> collect = a
                .stream()
//                .map(i -> b.stream().filter(j -> (i + j) % 3 == 0).map(j -> new int[]{i, j}));    // Stream<Stream<int[]>>
                .flatMap(i -> b.stream().filter(j -> (i + j) % 3 == 0).map(j -> new int[]{i, j}))   // Stream<int[]>
                .collect(Collectors.toList());                                                      // List<int[]>
        collect.stream().forEach(result -> {
            System.out.println(Arrays.toString(result));
        });
    }*/
//--------------------------------------------------------------------------------------------------
    // 查询1,2,3,4,5的平方第一个能被3整除的数
    /*public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
//        Optional<Integer> result = list.stream().filter(v -> v * v % 3 == 0).findFirst();
        Optional<Integer> result = list.stream().map(v -> v * v).filter(v -> v % 3 == 0).findFirst();
        System.out.println(result.get());// 9
    }*/
//--------------------------------------------------------------------------------------------------
    /*public static void main(String[] args) {
        Trader ming = new Trader("ming", "晋中");
        Trader ying = new Trader("ying", "唐山");
        Trader baby1 = new Trader("baby1", "上海");
        Trader baby2 = new Trader("baby2", "上海");

        List<Transaction> list = Arrays.asList(
                new Transaction(ming, 2019, 1000),
                new Transaction(ying, 2020, 2000),
                new Transaction(baby1, 2021, 3000),
                new Transaction(baby2, 2021, 4000)
        );

        // 1.找出2021年发生的所有交易，并按交易额排序(从低到高)
        List<Transaction> collect = list.stream()
                .filter(l -> 2021 == l.getYear())
                .sorted(Comparator.comparing(Transaction::getValue))
                .collect(Collectors.toList());
        System.out.println(collect);

        // 2.交易员都在那些不同的城市工作过
        List<String> collect1 = list.stream()
                .map(l -> l.getTrader().getCity())
                .distinct()
                .collect(Collectors.toList());
        System.out.println(collect1);
        Set<String> collect2 = list.stream()
                .map(l -> l.getTrader().getCity())
                .collect(Collectors.toSet());
        System.out.println(collect2);

        // 3.查找所有来自于上海的交易员，并按姓名排序
        List<Trader> collect3 = list.stream()
                .map(Transaction::getTrader)
                .filter(l -> "上海".equals(l.getCity()))
                .sorted(Comparator.comparing(Trader::getName).reversed())
                .collect(Collectors.toList());
        System.out.println(collect3);

        // 4.返回所有交易员的姓名字符串，按字母顺序排序
        String reduce = list.stream()
                .map(l -> l.getTrader().getName())
                .distinct()
                .sorted()
                .reduce("", (name1, name2) ->
                    !"".equals(name1) ? name1 + "," + name2 : name1 + name2
                );
        System.out.println(reduce);

        String collect4 = list.stream()
                .map(l -> l.getTrader().getName())
                .distinct()
                .sorted()
                .collect(Collectors.joining(","));
        System.out.println(collect4);

        // 5.有没有交易员是在唐山工作的
        boolean b = list.stream()
                .anyMatch(l -> "唐山".equals(l.getTrader().getCity()));
        System.out.println(b);

        // 6.打印生活在上海的交易员的所有交易金额
        list.stream()
                .filter(l -> "上海".equals(l.getTrader().getCity()))
                .map(l -> l.getTrader().getName() + ":" + l.getValue())
                .forEach(System.out::println);

        // 7.所有交易中，最高的交易额是多少
        Optional<Integer> max = list.stream()
                .map(Transaction::getValue)
                .reduce(Integer::max);
        System.out.println(max.get());

        // 8.找到交易额最小的交易
        Optional<Transaction> min1 = list.stream()
                .reduce((v1, v2) ->
                        v1.getValue() < v2.getValue() ? v1 : v2
                );
        System.out.println(min1.get());
        Optional<Transaction> min2 = list.stream()
                .min(Comparator.comparing(Transaction::getValue));
        System.out.println(min2.get());
    }*/
//--------------------------------------------------------------------------------------------------

    /*public static void main(String[] args) {
        // 勾股定理
        *//*IntStream.rangeClosed(1, 100)
                .boxed()
                .flatMap(a -> IntStream.rangeClosed(a, 100)
                        .filter(b -> Math.sqrt(a * a + b * b) % 1 == 0)
                        .mapToObj(b -> new int[]{a, b, (int) Math.sqrt(a * a + b * b)}))
                .forEach(l -> System.out.println("l = " + Arrays.toString(l)));*//*

        System.out.println("-----------------------------------------------------------------------");

        *//*IntStream.rangeClosed(1, 100)
                .boxed()
                .flatMap(a -> IntStream.rangeClosed(a, 100)
                        .mapToObj(b -> new double[]{a, b, Math.sqrt(a * a + b * b)})
                        .filter(c -> c[2] % 1 == 0))
                .forEach(l -> System.out.println("l = " + Arrays.toString(l)));*//*
//--------------------------------------------------------------------------------------------------
        // 斐波那契数列
        *//*Stream.iterate(new int[]{0, 1}, l -> new int[]{l[1], l[0] + l[1]})
                .limit(20)
                .forEach(l -> System.out.println("(" + l[0] + "," + l[1] + ")"));*//*
//--------------------------------------------------------------------------------------------------
        // 无限流
        *//*Stream.generate(Math::random)
                .limit(10)
                .forEach(System.out::println);*//*

        *//*IntStream ones = IntStream.generate(() -> 1);
        IntStream twos = IntStream.generate(new IntSupplier() {
            @Override
            public int getAsInt() {
                return 2;
            }
        });*//*

        *//*Stream<Integer> stream = Arrays.asList(1, 2, 3, 4, 5).stream();
        stream.reduce(
                new ArrayList<Integer>(), (List<Integer> l1, Integer l2) -> {
                    l1.add(l2);
                    return l1;
                }, (List<Integer> l1, List<Integer> l2) -> {
                    l1.addAll(l2);
                    return l1;
                }).forEach(l -> System.out.println(l.toString()));
        List<String> list = Arrays.asList("1", "2", "3", "4", "5");
        String s = list.stream().collect(Collectors.reducing((a, b) -> a + b)).get();*//*
    }*/
//--------------------------------------------------------------------------------------------------
    /*// 将数字按质数和非质数分区
    // range不包含最后的结束节点，rangeClosed包含最后的结束节点

    // 2--n的质数
    public  boolean isPrime(int candidate) {
        return IntStream.range(2, candidate).noneMatch(i -> candidate % i == 0);
    }
    // 2--根号n的质数
    public static boolean isPrime(int candidate) {
        int candidateRoot = (int) Math.sqrt((double) candidate);
        return IntStream.rangeClosed(2, candidateRoot).noneMatch(i -> candidate % i == 0);
    }
    // 按照是不是质数进行分组
    public static Map<Boolean, List<Integer>> partitionPrimes(int n) {
        return IntStream.rangeClosed(2, n).boxed()
                .collect(Collectors.partitioningBy(candidate -> isPrime(candidate)));
    }

    // 输出2---10之内的质数
    public static void main(String[] args) {
        partitionPrimes(10).forEach((a, b) -> {
            if (a) {
                b.forEach(c -> System.out.println(c));
            }
        });
    }*/
//--------------------------------------------------------------------------------------------------
/*    public static long iterativeSum(long n) {
//        long result = 0;
//        for(long i = 1L; i<=n; i++) {
//            result += i;
//        }
//        return result;

//        return Stream.iterate(1L, i -> i + 1)
//                .limit(n)
//                .reduce(0L, Long::sum);

        return Stream.iterate(1L, i -> i + 1)
                .limit(n)
                .parallel()
                .reduce(0L, Long::sum);
    }
    public static void main(String[] args) {
        long l = iterativeSum(3);
        System.out.println(l);
    }*/
//--------------------------------------------------------------------------------------------------
    public static long measureSumPerf(Function<Long, Long> adder, long n) {
        long fastest = Long.MAX_VALUE;
        for (int i = 0; i < 10; i++) {
            long start = System.nanoTime();
            long sum = adder.apply(n);
            long duration = (System.nanoTime() - start) / 1_000_000;
            System.out.println("Result: " + sum);
            if (duration < fastest) {
                fastest = duration;
            }
        }
        return fastest;
    }

    public static void main(String[] args) {

    }
}
